/*
 * SimulationDialog.java
 *
 * Created on Pondelok, 2007, november 12, 0:01
 */

package gui;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
import javax.swing.JFileChooser;
import javax.swing.SwingWorker;
import javax.swing.table.DefaultTableModel;
import logic.JSimulation;
import logic.SimulationRunState;
import logic.Statistic;
import logic.SwingSimulationMultiple;
import logic.SwingSimulationOneRun;
import xml.XmlStatistics;

/**
 *
 * @author  alvin
 */
public class SimulationDialogMultiple extends javax.swing.JDialog
        implements SwingSimulationMultiple.StateChangeListener  {
    
    private JFileChooser fileChooser = new JFileChooser();
    
    public SimulationDialogMultiple(javax.swing.JFrame owner) {
        super(owner, true);
        initComponents();
        saveCSVBtn.setVisible(false);
    }
    
    private boolean running = false;
    private boolean forceStop = false;
    SwingSimulationMultiple simulation;
    LinkedList<Statistic> results;
    
    public void start() {
        System.out.println("SimulationDialogMultiple.start()");
        
        running = false;
        forceStop = false;
        startStopBtn.setText(running ? "Stop" : "Start");
        startStopBtn.setEnabled(true);
        
        saveCSVBtn.setEnabled(false);
        saveXMLBtn.setEnabled(false);
        closeBtn.setEnabled(false);
        while (resultsTab.getRowCount() > 0)
            ((DefaultTableModel)resultsTab.getModel()).removeRow(0);
        resultsTab.setEnabled(false);
        
        
        if (results != null)
            results.clear();
        
        simulation = new SwingSimulationMultiple();
        simulation.addStateChangeListener(this);
    }
    
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        simulationProgress = new javax.swing.JProgressBar();
        startStopBtn = new javax.swing.JButton();
        simulationStateDesc = new javax.swing.JLabel();
        closeBtn = new javax.swing.JButton();
        saveXMLBtn = new javax.swing.JButton();
        saveCSVBtn = new javax.swing.JButton();
        resultsLbl = new javax.swing.JLabel();
        runsCountLbl = new javax.swing.JLabel();
        simRunsCountTxF = new javax.swing.JTextField();
        jScrollPane1 = new javax.swing.JScrollPane();
        resultsTab = new javax.swing.JTable();

        setTitle("Simulation");
        simulationProgress.setStringPainted(true);

        startStopBtn.setText("Start");
        startStopBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startStopBtnActionPerformed(evt);
            }
        });

        simulationStateDesc.setText("state");

        closeBtn.setText("Close");
        closeBtn.setMaximumSize(new java.awt.Dimension(92, 25));
        closeBtn.setMinimumSize(new java.awt.Dimension(92, 25));
        closeBtn.setPreferredSize(new java.awt.Dimension(92, 25));
        closeBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeBtnActionPerformed(evt);
            }
        });

        saveXMLBtn.setText("Save XML");
        saveXMLBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveXMLBtnActionPerformed(evt);
            }
        });

        saveCSVBtn.setText("Save CSV");
        saveCSVBtn.setMaximumSize(new java.awt.Dimension(92, 25));
        saveCSVBtn.setMinimumSize(new java.awt.Dimension(92, 25));
        saveCSVBtn.setPreferredSize(new java.awt.Dimension(92, 25));

        resultsLbl.setText("Results");

        runsCountLbl.setText("Simulation runs count:");

        simRunsCountTxF.setText("10");

        resultsTab.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Entity", "Statistic", "Interval begin", "Interval end"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.Double.class, java.lang.Double.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jScrollPane1.setViewportView(resultsTab);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(resultsLbl)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 345, Short.MAX_VALUE)
                        .addComponent(startStopBtn))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(runsCountLbl)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(simRunsCountTxF, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(simulationStateDesc, javax.swing.GroupLayout.DEFAULT_SIZE, 454, Short.MAX_VALUE)
                    .addComponent(simulationProgress, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 454, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(saveCSVBtn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(saveXMLBtn)
                        .addGap(15, 15, 15)
                        .addComponent(closeBtn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(runsCountLbl)
                    .addComponent(simRunsCountTxF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(simulationStateDesc, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(simulationProgress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(startStopBtn)
                    .addComponent(resultsLbl))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(closeBtn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(saveXMLBtn)
                    .addComponent(saveCSVBtn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        pack();
    }// </editor-fold>//GEN-END:initComponents
    
    private void saveXMLBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveXMLBtnActionPerformed
        if (results != null) {
            //TODO: nove riadky v subore
            try {
                int return_val = fileChooser.showSaveDialog(this);
                if(return_val == fileChooser.APPROVE_OPTION) {
                    String subor = fileChooser.getSelectedFile().getAbsolutePath();
                    if(subor.length() > 4) {
                        if (!subor.substring(subor.length() - 4).equals(".xml")) {
                            subor = subor.concat(".xml") ;
                        }
                        
                    }
                    XmlStatistics.saveSimulationResults(results, subor);
                }
            } catch (Exception ex) {
                ((GangstersGrid) this.getOwner()).showErrorMessage(ex.getMessage());
            }
        }
    }//GEN-LAST:event_saveXMLBtnActionPerformed
    
    private void closeBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeBtnActionPerformed
        setVisible(false);
    }//GEN-LAST:event_closeBtnActionPerformed
    
    private void startStopBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startStopBtnActionPerformed
        if (running) {
            startStopBtn.setEnabled(false);
            forceStop = true;
            System.out.println("Stop simulation..");
            simulation.stopExecuting();
        } else {
            
            int runsCount = 3;
            try {
                runsCount = Integer.parseInt(simRunsCountTxF.getText());
                if (runsCount <= 0) {
                    GangstersGrid.showErrorMessage("Value of runs count must be greater than zero.");
                    return;
                }
            } catch (NumberFormatException ex2) {
                GangstersGrid.showErrorMessage("Value of runs count must be a number.");
                return;
            }
            
            startStopBtn.setText("Stop");
            simulation.setRunsCount(runsCount);
            simulation.execute();
            running = true;
        }
        
    }//GEN-LAST:event_startStopBtnActionPerformed
    
    public void StateChanged(SwingSimulationMultiple.SimulationState newState) {
        String desc = newState.getDescription();
        switch (newState.state) {
            case SimulationRunState.STATE_RUNNING:
                int done = newState.runIndex;
                int all = simulation.getRunsCount();
                desc = desc +
                        " - run no. " + Integer.toString(done) +
                        " of " + Integer.toString(all);
                simulationProgress.setValue(done*100/all);
                break;
            case SimulationRunState.STATE_INIT:
                simulationProgress.setValue(0);
                break;
            case SimulationRunState.STATE_FINISHING:
            case SimulationRunState.STATE_FINISHED:
                simulationProgress.setValue(100);
                break;
            case SimulationRunState.STATE_WAITING_FOR_START:
                simulationProgress.setValue(0);
                break;
            default:
                break;
        }
        simulationStateDesc.setText(desc + ".");
    }
    
    public void showResults() {
        while (resultsTab.getRowCount() > 0)
            ((DefaultTableModel)resultsTab.getModel()).removeRow(0);
        resultsTab.setEnabled(true);
        
        if (results != null) {
            for (Statistic stat : results) {
                Object[] data = new Object[4];
                data[0] = stat.getEntityName();
                data[1] = stat.typeToStr();
                data[2] = stat.getIntervalEstamination().minimum;
                data[3] = stat.getIntervalEstamination().maximum;
                ((DefaultTableModel)resultsTab.getModel()).addRow(data);
            }
        }
    }
    
    public void simulationFinished() {
        startStopBtn.setEnabled(false);
        try {
            if (!forceStop) {
                results = simulation.get();
//                System.out.println("Showing simulation results " + results.size());
                saveCSVBtn.setEnabled(true);
                saveXMLBtn.setEnabled(true);
                showResults();
            } else {
//                System.out.println("Forced stop");
                results = null;
            }
            closeBtn.setEnabled(true);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } catch (ExecutionException ex) {
            ex.printStackTrace();
        }
    }
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton closeBtn;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel resultsLbl;
    private javax.swing.JTable resultsTab;
    private javax.swing.JLabel runsCountLbl;
    private javax.swing.JButton saveCSVBtn;
    private javax.swing.JButton saveXMLBtn;
    private javax.swing.JTextField simRunsCountTxF;
    private javax.swing.JProgressBar simulationProgress;
    private javax.swing.JLabel simulationStateDesc;
    private javax.swing.JButton startStopBtn;
    // End of variables declaration//GEN-END:variables
    
}
